unittest.mock.Mock で isinstance 関数を通り抜けるモックオブジェクトを作成する方法

unittest.mock.Mock で isinstance 関数を通り抜けるモックオブジェクトを作成する方法

unittest.mock.Mockのspec属性を利用することで、isinstance 関数を通り抜けるモックオブジェクトを作成しました
Clock Icon2025.01.21

はじめに

こんにちは、アノテーションのなかたです。
今回は、unittest.mock.Mockで isinstance関数を通過させる方法についてです。

結論

以下のコードで通過させることができました。

from unittest.mock import Mock

mock_instance = Mock(spec=クラス)

背景

次のように、Pointクラスと、Pointインスタンスを想定した関数があるとします。
Point インスタンスのみを確実に通すため、isinstance関数によるチェックを実装しています。

class Point:
    def __init__(self, x: int, y: int):
        self.x = x
        self.y = y

def output_point(point: Point):
    if not isinstance(point, Point):
        raise ValueError("point is not Point instance")

    return f"x: {point.x}, y: {point.y}"

output_point関数をテストする際、次のようにMockで属性を変更しただけでは、isinstance 関数により弾かれてしまいます。

def test_output_area():
    mock_point = Mock()
    mock_point.x = 10
    mock_point.y = 20

    assert output_point(mock_point) == "x: 10, y: 20"  # ValueError: point is not Point instance

次のように、spec属性でクラスを設定することで、Pointクラスを偽装することができます。

def test_output_area():
    mock_point = Mock(spec=Point)  # spec属性でPointクラスを設定
    mock_point.x = 10
    mock_point.y = 20

    assert output_point(mock_point) == "x: 10, y: 20"

おわりに

unittest.mock.Mock には wraps属性など、specの他にも便利そうなものがありましたので、こちらも使い方を紹介できればと思います。

参考

https://docs.python.org/ja/3.13/library/unittest.mock.html#the-mock-class

アノテーション株式会社について

アノテーション株式会社はクラスメソッドグループのオペレーション専門特化企業です。サポート・運用・開発保守・情シス・バックオフィスの専門チームが、最新 IT テクノロジー、高い技術力、蓄積されたノウハウをフル活用し、お客様の課題解決を行っています。当社は様々な職種でメンバーを募集しています。「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、アノテーション株式会社 採用サイトをぜひご覧ください。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.